package com.xybian.services.impl;

import com.xybian.common.CommonResult;
import com.xybian.entity.SysUser;
import com.xybian.services.LoginService;
import com.xybian.util.JwtTokenUtil;
import org.apache.tomcat.websocket.AuthenticationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 登录服务实现类
 *
 * @author SongRenShuo
 * @date 2023-12-23
 */
@Service
public class LoginServiceImpl implements LoginService {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 登录
     *
     * @param user 用户
     * @return 通用返回对象
     * @throws AuthenticationException 身份验证异常
     */
    @Override
    public CommonResult login(SysUser user) throws AuthenticationException {

        //封装 Authentication
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user.getUserName(),user.getPassword());

        //认证用户
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);

        if (authenticate == null){
            throw new AuthenticationException("认证失败");
        }

        UserDetailsImpl userDetails = (UserDetailsImpl)authenticate.getPrincipal();
        SysUser sysUser = userDetails.getSysUser();
        List<String> permissions = userDetails.getPermissions();

        sysUser.setPermissions(permissions);


        //认证通过，生成jwt
        Map<String, Object> map = new HashMap<>();
        map.put("userId",sysUser.getId());
        String token = jwtTokenUtil.generateToken(map);

        //用户信息存入 redis 中
        redisTemplate.opsForValue().set("user-"+sysUser.getId(),sysUser);

        //将token信息返回
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("token",token);
        return CommonResult.success(dataMap);
    }


    /**
     * 注销
     * 因为每一次请求都是一个新的 securityContextHolder，所以将 redis 中用户信息删除后，
     * 在用token访问接口时，在获取 redis 用户信息时，无法通过，即注销成功。
     *
     * @return 通用返回对象
     */
    @Override
    public CommonResult logout() {
        //获取 securityContextHolder
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        SysUser user = (SysUser)authentication.getPrincipal();


        //删除redis中的用户信息
        redisTemplate.delete("user-"+user.getId());

        return CommonResult.success("注销成功",null);
    }
}
